import base64
import io
import json
import numpy as np
import requests
import xlsxwriter

from django.contrib.auth.decorators import login_required
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render, redirect
from django.template.loader import render_to_string
from django.views.decorators.clickjacking import xframe_options_sameorigin
from django.views.decorators.csrf import csrf_exempt
from skimage import io as skimage_io, color, exposure
from skimage import draw as skimage_draw
from skimage import filters
from datetime import datetime, timedelta
from PIL import Image

from al120.forms import SampleForm
from al120.models import AlSample


def index_view(request):
    return render(request, 'al120/index_float.html')


def about_view(request):
    return render(request, 'al120/about.html')


# 新建记录
def create_sample(request):
    if request.method == 'POST':
        ret = {'status': False}
        p = request.POST.copy()
        dt = p['sample_time']
        if dt == '':
            dt = datetime.now()
        else:
            dt = datetime.strptime(dt, '%Y-%m-%dT%H:%M')
        p['sample_time'] = dt
        p['recorder'] = request.user.username

        form = SampleForm(p)
        if form.is_valid():
            try:
                form.save()
                ret['status'] = True
            except Exception as e:
                print(str(e))
                ret['err'] = str(e)
        ret['err'] = form.errors.as_text()
        return JsonResponse(ret)


# 查看
def sample_view(request):
    if request.method == 'POST':
        ret = {'status': False}
        dt = request.POST['sample_date']
        dt = datetime.strptime(dt, '%Y-%m-%d')
        dt_2 = dt + timedelta(hours=24)
        qs = AlSample.objects.filter(sample_time__gte=dt, sample_time__lt=dt_2).order_by('-id')
        sample_list = []
        if qs.count() > 0:
            ret['status'] = True
            c = qs.count()
            for q in qs:
                if q.al > 1000:
                    si = q.si / 1000
                    fe = q.fe / 1000
                    cu = q.cu / 100000
                    mn = q.mn / 10000
                    mg = q.mg / 1000
                    zn = q.zn / 10000
                    ti = q.ti / 1000
                    ca = q.ca / 100000
                    sb = q.sb / 10000
                    sr = q.sr / 10000
                else:
                    si = q.si
                    fe = q.fe
                    cu = q.cu
                    mn = q.mn
                    mg = q.mg
                    zn = q.zn
                    ti = q.ti
                    ca = q.ca
                    sb = q.sb
                    sr = q.sr
                tmp = {'si': si, 'fe': fe, 'cu': cu, 'mn': mn, 'mg': mg, 'zn': zn,
                       'ti': ti, 'ca': ca, 'sb': sb, 'sr': sr,
                       'color_si': '#00FF00' if 6.5 <= si < 7.5 else '#FF0000',
                       'color_fe': '#00FF00' if fe < 0.15 else '#FF0000',
                       'color_cu': '#00FF00' if cu < 0.20 else '#FF0000',
                       'color_mn': '#00FF00' if mn < 0.05 else '#FF0000',
                       'color_mg': '#00FF00' if 0.25 <= mg < 0.4 else '#FF0000',
                       'color_zn': '#00FF00' if zn < 0.10 else '#FF0000',
                       'color_ti': '#00FF00' if ti < 0.20 else '#FF0000',
                       'color_ca': '#00FF00' if ca < 0.01 else '#FF0000',
                       'color_sb': '#00FF00' if sb < 0.15 else '#FF0000',
                       'color_sr': '#00FF00' if 0.004 <= sr < 0.012 else '#FF0000',
                       'recorder': q.recorder,
                       'sample_source': q.sample_source,
                       'sample_time': q.sample_time,
                       }
                sample_list.append(tmp)
                # render
                html = render_to_string('al120/partial_sample.html', {'data': sample_list, 'count': c})
                ret['html'] = html
                ret['data'] = sample_list

        return JsonResponse(ret)
    return render(request, 'al120/view_sample.html')


# 图表
def chart_view(request):
    return render(request, 'al120/chart.html')


def chart_data(request):
    if request.method == 'POST':
        ret = {'status': False}
        # 日期范围
        s = request.POST['s']
        e = request.POST['e']
        date_s = datetime.strptime(s, '%Y-%m-%d')
        date_e = datetime.strptime(e, '%Y-%m-%d')
        date_e += timedelta(days=1)
        qs = AlSample.objects.filter(sample_time__gte=date_s, sample_time__lt=date_e).order_by('-sample_time')
        if qs.count() > 0:
            ret['status'] = True
            qs = list(reversed(qs))
            fe = [[int(q.sample_time.timestamp()) * 1000, q.fe if q.fe > 1 else q.fe * 1000] for q in qs]
            si = [[int(q.sample_time.timestamp()) * 1000, q.si if q.cu > 1 else q.si * 10] for q in qs]
            mg = [[int(q.sample_time.timestamp()) * 1000, q.mg if q.mg > 1 else q.mg * 100] for q in qs]
            ret['data'] = [
                {
                    'name': 'Si',
                    'data': si,
                    # 'yAxis': 0
                },
                {
                    'name': 'Fe',
                    'data': fe,
                    # 'yAxis': 1
                },

                {
                    'name': 'Mg',
                    'data': mg,
                    # 'yAxis': 2
                },
            ]

        return JsonResponse(ret)


def write_excel(data):
    output = io.BytesIO()
    workbook = xlsxwriter.Workbook(output, {'in_memory': True})

    # 格式
    bold = workbook.add_format({'bold': 1})
    cell_format = workbook.add_format()
    cell_format.set_align('left')
    cell_format.set_align('vcenter')
    cell_format.set_text_wrap()

    hidden = workbook.add_format()
    hidden.set_hidden()

    title = '铝液检测日志'
    workbook.add_worksheet(name=title)
    worksheet = workbook.get_worksheet_by_name(title)
    # 激活工作表
    worksheet.activate()
    worksheet.set_default_row(21)  # 行高
    worksheet.set_column('B:B', 20)
    # worksheet.set_column('B:B', 10)
    # worksheet.set_column('C:C', 300)

    row_1 = ['来源', '时间', 'Si', 'Fe', 'Cu', 'Mn', 'Mg', 'Zn', 'Ti', 'Ca', 'Sb', 'Sr']
    for i, v in enumerate(row_1):
        worksheet.write(1, i, v)

    row_2 = ['标准', '', '6.5~7.5', '<0.15', '<0.20', '<0.05', '0.25~0.4', '<0.10', '<0.20', '<0.01', '<0.15',
             '0.004~0.012', ]
    for i, v in enumerate(row_2):
        worksheet.write(2, i, v)

    # 标题
    merge_format = workbook.add_format({
        'bold': True,
        'border': 6,
        'align': 'center',  # 水平居中
        'valign': 'vcenter',  # 垂直居中
        'font_color': '#D7E4BC',  # 颜色填充
    })

    worksheet.merge_range('A1:L1', title, merge_format)

    row = 3
    for d in data:
        worksheet.write(row, 0, d['sample_source'])
        worksheet.write(row, 1, d['sample_time'], workbook.add_format({'num_format': 'hh:mm'}))
        worksheet.write(row, 2, d['si'], workbook.add_format({'font_color': d['color_si']}))
        worksheet.write(row, 3, d['fe'], workbook.add_format({'font_color': d['color_fe']}))
        worksheet.write(row, 4, d['cu'], workbook.add_format({'font_color': d['color_cu']}))
        worksheet.write(row, 5, d['mn'], workbook.add_format({'font_color': d['color_mn']}))
        worksheet.write(row, 6, d['mg'], workbook.add_format({'font_color': d['color_mg']}))
        worksheet.write(row, 7, d['zn'], workbook.add_format({'font_color': d['color_zn']}))
        worksheet.write(row, 8, d['ti'], workbook.add_format({'font_color': d['color_ti']}))
        worksheet.write(row, 9, d['ca'], workbook.add_format({'font_color': d['color_ca']}))
        worksheet.write(row, 10, d['sb'], workbook.add_format({'font_color': d['color_sb']}))
        worksheet.write(row, 11, d['sr'], workbook.add_format({'font_color': d['color_sr']}))

        row += 1
    # 图表
    chart = workbook.add_chart({'type': 'line'})
    data_fe = [d['fe'] for d in data]
    data_fe_t = [d['sample_time'] for d in data]
    data_cu = [d['cu'] for d in data]
    data_cu_t = [d['sample_time'] for d in data]

    worksheet.write_column('M1', data_fe)
    worksheet.write_column('N1', data_fe_t)
    worksheet.write_column('O1', data_cu)
    worksheet.write_column('P1', data_cu_t)
    chart.add_series({
        'name': 'Fe',
        'values': '=%s!$M$1:$M$%d' % (title, len(data_fe)),
        'categories': '=%s!$N$1:$N$%d' % (title, len(data_fe_t))
    })
    chart.add_series({
        'name': 'Cu',
        'values': '=%s!$O$1:$O$%d' % (title, len(data_cu)),
        'categories': '=%s!$P$1:$P$%d' % (title, len(data_cu_t))
    })

    # 插入表
    worksheet.insert_chart('A%d' % (row + 3), chart)

    workbook.close()
    output.seek(0)
    return output


# 导出excel
def your_excel(request):
    if request.method == 'GET':
        data = json.loads(request.GET['data'])
        # 生成excel
        output = write_excel(data)
        # 输出xls文件
        response = HttpResponse()
        response["Content-Type"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        response['Content-Disposition'] = 'attachment;filename=铝液检测日志.xlsx'
        response.write(output.getvalue())

        return response


# 图片识别
def to_base64(image):
    return base64.b64encode(image).decode('utf8')


def rc(file, x, y, w, h):
    headers = {'content-type': 'application/json'}
    url = 'http://123.168.9.134:8866/predict/ocr_system'

    image = Image.open(file)  # 读bytesio
    f = np.asarray(image, dtype=np.uint8)  # 转换到np
    # f = exposure.equalize_adapthist(f)
    # 剪裁
    roi = f[y:y + h, x:x + w]
    # ndarray ---> 内存png
    roi_gray = color.rgb2gray(color.rgba2rgb(roi))
    roi_gray = exposure.equalize_adapthist(roi_gray)
    # thresh = filters.threshold_mean(roi_gray)
    # roi_binary = roi_gray > thresh
    # roi_gray = np.uint8((roi_gray * 255))
    roi_gray = (roi_gray * 255).astype(np.uint8)
    roi_img = Image.fromarray(roi_gray)
    buf = io.BytesIO()
    roi_img.save(buf, format='png')

    data = {'images': [to_base64(buf.getvalue())]}

    ret = {'status': False}
    r = requests.post(url=url, headers=headers, data=json.dumps(data))
    if r.json()['status'] == '000':
        res = r.json()['results'][0]

        if len(res) > 0:
            # 排序
            result = {}
            for res_s in res:
                result[res_s['text_region'][0][0]] = res_s['text']
            result_sorted = sorted(result)
            text = [result[i].replace('<', '') for i in result_sorted]
            print(len(text), text)
            # 画结果
            img = roi.copy()
            for res_s in res:
                res0 = res_s['text_region']
                r = np.array([res0[0][1], res0[1][1], res0[2][1], res0[3][1]])
                c = np.array([res0[0][0], res0[1][0], res0[2][0], res0[3][0]])
                rr, cc = skimage_draw.polygon_perimeter(r, c, img.shape)

                img[rr, cc] = 255

            # 编码base64， 返回
            # skimage_io.imsave('e:/abc2.png', img)  # debug 1
            ocr_img = Image.fromarray(img)
            ocr_img.save(buf, format='png')
            img_b64 = to_base64(buf.getvalue())
            ret['status'] = True
            ret['text'] = text
            ret['img'] = img_b64

            return ret


@csrf_exempt
def ocr(request):
    if request.method == 'POST':
        file = request.FILES['file']
        x = int(request.POST['x'])
        y = int(request.POST['y'])
        w = int(request.POST['w'])
        h = int(request.POST['h'])

        f = io.BytesIO()
        for c in file.chunks():
            f.write(c)
        ret = rc(f, x, y, w, h)
        return JsonResponse(ret)

    return render(request, 'al120/ocr.html')


@xframe_options_sameorigin
def ocr_c(request):
    if request.method == 'GET':
        txt = request.GET['txt']
        txt = txt.split(',')
        # img = request.GET['img']
        return render(request, 'al120/index_ocr_confirm.html', {'text': txt})
